package pl.edu.mimuw.irs.rcp.view;

import java.util.Map;
import java.util.Set;

import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.ViewPart;

import pl.edu.mimuw.irs.core.model.design.IRSWorkflow;
import pl.edu.mimuw.irs.core.model.design.processing.Resource;
import pl.edu.mimuw.irs.core.model.design.processing.Role;
import pl.edu.mimuw.irs.rcp.controller.editor.IRSWorkflowEditor;
import pl.edu.mimuw.irs.rcp.controller.editor.ResourceEditor;
import pl.edu.mimuw.irs.rcp.view.resources.ResourcesViewContentProvider;
import pl.edu.mimuw.irs.rcp.view.resources.ResourcesViewLabelProvider;

/**
 * @author Jakub Rauch
 * Created on: 2009-05-25
 */
public class ResourcesView extends ViewPart {

	public static final String ID = "pl.edu.mimuw.irs.view.resources";

	// *** Attributes
	
	private TableViewer viewer;
	private IRSWorkflow model;
	private ISelectionListener listener = new ISelectionListener() {
		@Override
		public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
			// we ignore our own selections
			if (sourcepart != ResourcesView.this) {
			    showSelection(sourcepart, selection);
			}
		}
	};
	public Map<String, Role> getRolesMap() {
		if (model != null) return model.getRolesMap();
		else return null;
	}
	
	// *** Constructors

	public ResourcesView() {
		super();
	}

	// *** Methods

	private void showSelection(IWorkbenchPart sourcepart,
			ISelection selection) {
		setContentDescription(sourcepart.getTitle() + " (" + selection.getClass().getName() + ")");

		if (sourcepart instanceof IRSWorkflowEditor) {
			IRSWorkflowEditor editor = (IRSWorkflowEditor) sourcepart;
			model = editor.getModel();
			Set<Resource> resources = model.getResources();
			if (viewer.getInput() != resources) {
				viewer.setInput(resources);
			}
		}
		//if (selection instanceof IStructuredSelection) {
		//	IStructuredSelection ss = (IStructuredSelection) selection;
		//	showItems(ss.toArray());
		//}
	}
	

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL);
		viewer.setContentProvider(new ResourcesViewContentProvider(viewer));
		viewer.setLabelProvider(new ResourcesViewLabelProvider());
		viewer.setInput(null);
		getSite().setSelectionProvider(viewer);
		getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(listener);
		
		addDragSource((Table)viewer.getControl());
		addDropTarget(viewer.getControl());
		
		hookDoubleClickCommand();
	}

	private void addDragSource(final Table tblContainers) {
		int operations = DND.DROP_COPY | DND.DROP_LINK;
		DragSource source = new DragSource(tblContainers, operations);
		
		Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
	 	source.setTransfer(types);
		
	 	source.addDragListener(new DragSourceListener() {
	 		public void dragStart(DragSourceEvent event) {
	 			// Only start the drag if there is actually text in the
	 			// label - this text will be what is dropped on the target.
	 			if (tblContainers.getSelection().length == 0) {
	 				event.doit = false;
	 			}
	 		}
	 		public void dragSetData(DragSourceEvent event) {
	 			// Provide the data of the requested type.
	 			if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
	 				Object[] selection = tblContainers.getSelection();
	 				TableItem item = (TableItem)selection[0];
	 				Resource resource = (Resource)item.getData();
	 				event.data = resource.getName();
	 			}
	 		}
	 		public void dragFinished(DragSourceEvent event) {
		 	    // If a move operation has been performed, remove the data
		 	    // from the source
			    /*if (event.detail == DND.DROP_MOVE) {
			    	Resource resourceToDelete = null;
			    	int controlToDelete = -1;
			    	for (Resource resource : getContainer().getList()) {
			    		if (resource.getId().equals((String)event.data))
			    			resourceToDelete = resource;
			    	}
			    	for (int i = 0; i < tblResources.getItemCount(); i++) {
			    		if (tblResources.getItem(i).getData().equals(resourceToDelete)) 
			    			controlToDelete = i;
			    	}
			    	if (resourceToDelete != null) getContainer().getList().remove(resourceToDelete);
			    	if (controlToDelete >= 0) tblResources.remove(controlToDelete);
			    }*/
			}
		});
	}
	
	private void addDropTarget(Control control) {
		DropTarget target = new DropTarget(control, DND.DROP_MOVE
				| DND.DROP_COPY | DND.DROP_DEFAULT);
		Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
		target.setTransfer(types);
		target.addDropListener(new DropTargetAdapter() {
			public void dragEnter(DropTargetEvent event) {
				if (event.detail == DND.DROP_DEFAULT) {
					event.detail = (event.operations & DND.DROP_LINK) != 0 ? DND.DROP_LINK
							: DND.DROP_NONE;
				}
				for (int i = 0, n = event.dataTypes.length; i < n; i++) {
					if (TextTransfer.getInstance().isSupportedType(
							event.dataTypes[i])) {
						event.currentDataType = event.dataTypes[i];
					}
				}
			}

			public void dragOver(DropTargetEvent event) {
				event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL;
			}

			public void drop(DropTargetEvent event) {
				if (TextTransfer.getInstance().isSupportedType(
						event.currentDataType)) {
					DropTarget target = (DropTarget) event.widget;
					Table table = (Table) target.getControl();
					String data = (String) event.data;

					TableItem item = new TableItem(table, SWT.BORDER);
					item.setText(new String[] { data });
					table.redraw();
				}
			}
		});
	}
	
	private void hookDoubleClickCommand() {
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				IHandlerService handlerService = (IHandlerService) getSite()
						.getService(IHandlerService.class);
				
				try {
					handlerService.executeCommand(
							ResourceEditor.COMMAND_ID, null);
				} catch (Exception ex) {
					throw new RuntimeException(
							ResourceEditor.COMMAND_ID + " not found");
				}
			}
		});
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}
	
	
}
